# coding=utf-8

from ui.main import Ui_MainWindow
from ui.login import Ui_LoginWindow
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
from threading import Thread
import os
import time
import subprocess
import pymongo
from datetime import datetime,timedelta
import requests
import random
from bson import json_util as  json
import base64

class UnitSender(QObject):
    trigger = pyqtSignal()
    def __init__(self):
        super(UnitSender,self).__init__()


class mThread(Thread):
    def __init__(self, func, args, name=''):
        Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args
        self.result = self.func(*self.args)

    def get_result(self):
        try:
            return self.result
        except Exception:
            return None


class UI_Controller:
    
    def __init__(self,window):
        self._running = True
        self.window = window

    def resume(self):
        self._running = True

    def terminate(self):
        self._running = False

    def show(self):
        self.window.show()

    def hide(self):
        self.window.hide()

    def run(self, sleep):
        while self._running:
            self.update()
            time.sleep(sleep)

    def update(self):
        self.window.update_stat()
        self.window.fill_method()

class LoginWindow(QWidget, Ui_LoginWindow):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi(self)
        self.center()
        self.loginButton.clicked.connect(self.login)

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())


    def login_request(self):
        username = self.username_edit.text()
        password = self.password_edit.text()
        if username.strip() == "" or password.strip() == "":
            return (False, "账号与密码不能为空")
        try:
            s = requests.post(url="https://jkbz_auth.hnjky.org.cn/user/login",headers = {"Content-Type": "application/json"},data=json.dumps({"usercode": username, "password": password}))
        except:
            return (False, "网络错误")

        return (True,json.loads(s.content.decode("utf-8")))

    def login(self):
        p = mThread(func=self.login_request,args=())
        p.start()
        p.join()
        res,response = p.get_result()
        if res:
            if "success" in response:
                if response["success"]==True:
                    ui_controller.window.token = response["object"]["token"]
                else:
                    QMessageBox.information(ui_controller.window,"错误","账号或密码错误")
                    return
            else:
                QMessageBox.information(ui_controller.window,"未知错误","请联系创星")
                return 
        else:
            QMessageBox.information(ui_controller.window,"错误",response)
            return
        open("/tmp/token.txt",'w').write(response["object"]["token"])
        self.hide()
        ui_controller.show()

class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setupUi(self)
        self.center()

        self.end_time_edit.setPlainText("结束时间: "+datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        self.start_time_edit.setPlainText("开始时间: "+(datetime.now()-timedelta(hours=2)).strftime("%Y-%m-%d %H:%M:%S"))

        self.start_listen_button.clicked.connect(self.start_listen_clicked)
        self.stop_listen_button.clicked.connect(self.stop_listen_clicked)
        self.confirm_time_button.clicked.connect(self.confirm_time_clicked)
        self.pack_button.clicked.connect(self.package_clicked)
        self.left_upper_list.clicked.connect(self.left_upper_list_clicked)

        self.msg = {}
        self.new_msg = {}
        self.msg_subtype = {}
        self.msg_oid= {}

        self.update = False

        self.auto_bottom = True
        self.auto_bottom_count = 0

        self.fill_method = self.fill_by_msg

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def update_stat(self,custom_msg=None):

        if custom_msg == None:
            self.new_msg = {i["_id"]:i for i in msg_col.find()}
        else:
            print("custom")
            custom_msg = {i["_id"]:i for i in custom_msg}
            self.new_msg = custom_msg

        if len(self.new_msg) == len(self.msg):
            print("no update")
            self.update = False
        else:
            self.update = True
            self.msg = self.new_msg

            self.title_msg = {"SD":{},"PL":{},"DE":{}}
            for i in self.msg.items():
                msg_type = i[1]["msg"]["msg_type"]
                title =  i[1]["msg"]["title"]
                if msg_type == "SD":
                    if title in self.title_msg["SD"]:
                        self.title_msg["SD"][title].append(i)
                    else:
                        self.title_msg["SD"][title] = [i]
                elif msg_type == "PL":
                    if title in self.title_msg["PL"]:
                        self.title_msg["PL"][title].append(i)
                    else:
                        self.title_msg["PL"][title] = [i]
                elif msg_type == "DE":
                    if title in self.title_msg["DE"]:
                        self.title_msg["DE"][title].append(i)
                    else:
                        self.title_msg["DE"][title] = [i]


    def left_upper_list_clicked(self,item):
        if "全部" in item.data():
            print("msg filling")
            self.fill_method = self.fill_by_msg
        elif "共享" in item.data():
            print("sd_msg filling")
            self.fill_method = self.fill_by_sd_msg
        elif "交互" in item.data():
            print("pl_msg filling")
            self.fill_method = self.fill_by_pl_msg
        elif "基础" in item.data():
            print("de_msg filling")
            self.fill_method = self.fill_by_de_msg

        self.update = True
        self.fill_method()

    def fill_template(self,ui_method,click_method):
        #通用渲染
        send = UnitSender()
        send.trigger.connect(self.update_left_upper_list)
        send.trigger.emit()
        send.trigger.disconnect()
        #msg渲染
        send = UnitSender()
        send.trigger.connect(ui_method)
        send.trigger.emit()
        send.trigger.disconnect()
        #点击      
        try:
            self.right_upper_list.clicked.disconnect()
        except:
            pass
        self.right_upper_list.clicked.connect(click_method)

    def fill_by_msg(self):
        self.fill_template(self.update_right_upper_list_by_msg,self.msg_list_item_clicked)

    def fill_by_sd_msg(self):
        self.fill_template(self.update_right_upper_list_by_sd_msg,self.sd_msg_list_item_clicked)

    def fill_by_pl_msg(self):
        self.fill_template(self.update_right_upper_list_by_pl_msg,self.pl_msg_list_item_clicked)

    def fill_by_de_msg(self):
        self.fill_template(self.update_right_upper_list_by_de_msg,self.de_msg_list_item_clicked)


    def msg_list_item_clicked(self, item):

        self.auto_bottom = False

        #try:
        key = item.data()
        data = self.msg[key]
        temp = data.copy()
        temp["msg"]["msg_body"] ="略"
        dump = json.dumps(temp,ensure_ascii=False,indent=4)
        self.right_lower_text.setPlainText(dump)
        #except:
        #self.right_lower_text.setPlainText("该消息已被删除")

        self.auto_bottom_count = 0

    def sd_msg_list_item_clicked(self, item):

        self.auto_bottom = False

        try:
            key = item.data().split(": ")[0]
            data = self.title_msg["SD"][key]
            text = '\n'.join([i[0] for i in data])
            self.right_lower_text.setPlainText(text)
        except:
            self.right_lower_text.setPlainText("该类别的所有消息都被删除了")

        self.auto_bottom_count = 0

    def pl_msg_list_item_clicked(self, item):

        self.auto_bottom = False

        #try:
        key = item.data().split(": ")[0]
        data = self.title_msg["PL"][key]
        text = '\n'.join([i[0] for i in data])
        self.right_lower_text.setPlainText(text)
        #except:
        #    self.right_lower_text.setPlainText("该类别的所有消息都被删除了")

        self.auto_bottom_count = 0

    def de_msg_list_item_clicked(self, item):

        self.auto_bottom = False

        #try:
        key = item.data().split(": ")[0]
        data = self.title_msg["DE"][key]
        text = '\n'.join([i[0] for i in data])
        self.right_lower_text.setPlainText(text)
        #except:
        #    self.right_lower_text.setPlainText("该类别的所有消息都被删除了")

        self.auto_bottom_count = 0

    @pyqtSlot()
    def update_left_upper_list(self):
        if self.update:
            temp_data = [f"全部消息: {str(len(self.title_msg['SD'])+len(self.title_msg['PL'])).rjust(4,' ')} 类, {str(len(self.msg.keys())).rjust(5,' ')} 条",
                    f"共享文档: {str(len(self.title_msg['SD'])).rjust(4,' ')} 类, {str(sum([len(i[1]) for i in self.title_msg['SD'].items()])).rjust(5,' ')} 条",
                    f"交互规范: {str(len(self.title_msg['PL'])).rjust(4,' ')} 类, {str(sum([len(i[1]) for i in self.title_msg['PL'].items()])).rjust(5,' ')} 条",
                    f"基础数集: {str(len(self.title_msg['DE'])).rjust(4,' ')} 类, {str(sum([len(i[1]) for i in self.title_msg['DE'].items()])).rjust(5,' ')} 条"]
            #temp_data = [f"{[i[1] for i in self.title_msg['SD']]}"]
            temp = QStringListModel()
            temp.setStringList(temp_data)
            self.left_upper_list.setModel(temp)

    @pyqtSlot()
    def update_right_upper_list_by_msg(self):
        if self.update:
            self.auto_bottom_count+=1
            if self.auto_bottom_count>=2 and self.update:
                self.auto_bottom = True
            temp=QStringListModel()
            temp.setStringList(self.msg.keys())
            self.right_upper_list.setModel(temp)

    @pyqtSlot()
    def update_right_upper_list_by_sd_msg(self):
        if self.update:
            self.auto_bottom_count+=1
            if self.auto_bottom_count>=2 and self.update:
                self.auto_bottom = True
            temp=QStringListModel()
            temp.setStringList([f"{k}: {len(v)}" for (k,v) in self.title_msg["SD"].items()])
            self.right_upper_list.setModel(temp)

    @pyqtSlot()
    def update_right_upper_list_by_pl_msg(self):
        if self.update:
            self.auto_bottom_count+=1
            if self.auto_bottom_count>=2 and self.update:
                self.auto_bottom = True
            temp=QStringListModel()
            temp.setStringList([f"{k}: {len(v)}" for (k,v) in self.title_msg["PL"].items()])
            self.right_upper_list.setModel(temp)

    @pyqtSlot()
    def update_right_upper_list_by_de_msg(self):
        if self.update:
            self.auto_bottom_count+=1
            if self.auto_bottom_count>=2 and self.update:
                self.auto_bottom = True
            temp=QStringListModel()
            temp.setStringList([f"{k}: {len(v)}" for (k,v) in self.title_msg["DE"].items()])
            self.right_upper_list.setModel(temp)

    def confirm_time_clicked(self):
        
        self.stop_listen_clicked()
    
        try:
            raw_start_time_text = self.start_time_edit.toPlainText()
            start_time_text = raw_start_time_text.replace("开始时间: ","")
            start_time = datetime.strptime(start_time_text, "%Y-%m-%d %H:%M:%S")
        except:
            QMessageBox.information(window,"错误","开始时间格式不正确")
            return
    
        try:
            raw_end_time_text = self.end_time_edit.toPlainText()
            end_time_text = raw_end_time_text.replace("结束时间: ","")
            end_time = datetime.strptime(end_time_text, "%Y-%m-%d %H:%M:%S")
        except:
            QMessageBox.information(window,"错误","结束时间格式不正确")
            return
    
        msgs = msg_col.find({"create_time":{"$gte": start_time,"$lte": end_time}})

        # update data
        self.update_stat(msgs)
        self.fill_method()
    
    def random_msg_sample(self, size = 3):
        result = []

        for i in self.title_msg["SD"].items():
            if len(i[1])<size:
                result+=i[1]
                continue
            result+=random.sample(i[1],size)

        for i in self.title_msg["PL"].items():
            if len(i[1])<size:
                result+=i[1]
                continue
            result+=random.sample(i[1],size)

        for i in self.title_msg["DE"].items():
            if len(i[1])<size:
                result+=i[1]
                continue
            result+=random.sample(i[1],size)

        return result

    def package_clicked(self):

        #检查是否有数据
        self.stop_listen_clicked()
        if self.msg=={}:
            QMessageBox.information(self,"失败","请先获取数据")
            return

        #随机取样
        res = self.random_msg_sample(3)
        
        #检查临时目录是否已初始化
        if os.path.isdir(data_path):
            sub = os.scandir(data_path)
            for each in sub:
                p = subprocess.Popen("rm -rf "+each.path,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
                p.communicate()
                print("初始化"+each.name)
        

        #保存数据
        for (k,v) in res:
            save_path ="/".join([data_path,v["oid"],v["msg"]["msg_type"]])
            os.makedirs(save_path,exist_ok=True)
            save_file = save_path+"/"+'-'.join(v["_id"].split('-')[1:])+".xml"
            with open(save_file,'wb') as f:
                f.write(base64.b64encode(v["msg"]["msg_body"].encode()))
                #f.write(v["msg_info"]["msg_body"].encode())
        p = subprocess.Popen(f"cd {data_path}; for i in $(ls {data_path});do zip -r /home/trasen/Desktop/$i.zip ./$i;done",shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE)
        p.communicate()
        QMessageBox.information(self,"成功!","消息已打包在桌面")

    def start_listen_clicked(self):
        ui_controller.resume()
        p = Thread(target=ui_controller.run, args=(3,))
        p.setDaemon(True)
        p.start()
        self.setWindowTitle("湖南省互联互通测评数据汇聚中心(监听中) - 湖南创星")
    
    def stop_listen_clicked(self):
        self.setWindowTitle( "湖南省互联互通测评数据汇聚中心 - 湖南创星")
        ui_controller.terminate()
        print("stop update")


def init():
    global data_path
    global ps
    global msg_col

    current_path = '/'.join(os.path.abspath(__file__).split('/')[:-1])
    os.chdir(current_path)

    client = pymongo.MongoClient('mongodb://localhost:27017/')

    login = client.admin
    login.authenticate("root","trasen@321")

    db = client['starsink']
    msg_col = db['msg']

    data_path = '/home/trasen/Starsink/client/data'
    ps = []


def show_gui():
    global ui_controller

    app = QApplication(sys.argv)
    window = MainWindow()
    login = LoginWindow()
    if not os.path.isfile("/tmp/token.txt"):
        login.show()
    else:
        window.show()
        window.token = open("/tmp/token.txt",'r').read()
    ui_controller = UI_Controller(window) 
    sys.exit(app.exec_())


def start_all():
    init()
    show_gui()

if __name__ == "__main__":
    start_all()


